home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / PACKET / TFLINK10 / TFLNKSRC / TFLINK.C < prev    next >
C/C++ Source or Header  |  1996-04-14  |  7KB  |  233 lines

  1. /*
  2.  *-----------------------------------------------------------------------
  3.  *
  4.  * TFLINK - program to make TFPCX TSR running a Baycom modem on a
  5.  * COM port appear as a serial (HOST mode) TNC on a second COM port.
  6.  *
  7.  * tflink.c - main module for the TFLINK program
  8.  *
  9.  * This program glues together a standard serial COM port and the
  10.  * TFPCX Baycom driver TNC and firmware emulator program.  In this
  11.  * manner, a PC and Baycom modem can be used together to emulate a
  12.  * WA8DED host-mode TNC for other external programs, for example,
  13.  * TNT running on Linux.
  14.  *
  15.  *-----------------------------------------------------------------------
  16.  */
  17.  
  18. /* standard inclusion file */
  19. #define    MAIN_MODULE        1
  20. #include "tflink.h"
  21. #include "ibmcom.h"
  22.  
  23. /* imported routines */
  24. bool    tfpcx_check();
  25. u_int    tfpcx_version();
  26. bool    tfpcx_request();
  27. u_char    tfpcx_readch();
  28. void    tfpcx_writech( u_char );
  29.  
  30. bool    getopts( int, char** );
  31.  
  32.  
  33. /* local definitions */
  34. #define    TFLINK_VERSION        ((1 << 8) | 0)
  35. #define TSR_MEMORY        0x600
  36. #define    PIC_INTERRUPT_MASK_PORT    0x21
  37.  
  38. /* interrupt numbers */
  39. #define INT1C            0x1C
  40. #define    INT21            0x21
  41. #define    INT21_TSR        0x31
  42. #define    INT21_TERMINATE        0x4C
  43. #define    INT21_FREE_MEM        0x49
  44.  
  45.  
  46. /* module-local variables */
  47. static u_char        i8259bit;
  48. static void interrupt    (*old_int_1c)( void );
  49.  
  50.  
  51. /*-----------------------------------------------------------------------*/
  52. /*
  53.  * print out the options as they are set up so that the defaults are
  54.  * visible and any overrides confirmed.  -N switches this off.  Note
  55.  * that this routine predicts the base address ibmcom will use.
  56.  */
  57. void printopts() {
  58.     const int    uart_base[] =    { 0x3F8, 0x2F8, 0x3E8, 0x2E8 };
  59.     int    i, width;    /* loop counter, box width */
  60.  
  61.     /* set box width to 43 chars */
  62.     width = 43;
  63.  
  64.     /* create a pretty box */
  65.     printf( "%c", 0xda );
  66.     for ( i=0; i<width-2; i++ ) printf( "%c", 0xc4 );
  67.     printf( "%c\n", 0xbf );
  68.     printf( "%c TFLINK version %2d.%02d - G0FRD            %c\n", 0xb3, 
  69.                 (u_int)(TFLINK_VERSION >> 8),
  70.                  (u_int)(TFLINK_VERSION & 0xFF), 0xb3 );
  71.     printf( "%c TFPCX - interrupt 0x%02X                  %c\n",
  72.             0xb3, tfpcx_interrupt, 0xb3 );
  73.     printf( "%c COM%1d  - base address 0x%04X, %5d baud %c\n",
  74.             0xb3, sio_port, uart_base[sio_port-1], sio_baud, 0xb3 );
  75.     printf( "%c", 0xc0 );
  76.     for ( i=0; i<width-2; i++ ) printf( "%c", 0xc4 );
  77.     printf( "%c\n", 0xd9 );
  78. }
  79.  
  80.  
  81. /*-----------------------------------------------------------------------*/
  82. /*
  83.  * timer interrupt handler - polls TFPCX for outgoing characters
  84.  */
  85. void interrupt int_1c( void )
  86. {
  87.     union    REGS inr,outr;        /* registers */
  88.     struct    SREGS sr;        /* registers */
  89.  
  90.     /* pass on to the original routine */
  91.     (*old_int_1c)();
  92.  
  93.     /* see if UART interrupts are off - indicates request from
  94.        foreground to terminate */
  95.     if ( inportb( PIC_INTERRUPT_MASK_PORT ) & i8259bit ) {
  96.  
  97.         /* unhook the timer vector */
  98.         disable();
  99.         setvect( INT1C, old_int_1c );
  100.         enable();
  101.  
  102.         /* deactivate the COM driver */
  103.         com_deinstall();
  104.  
  105.         /* all done */
  106.         inr.h.ah = INT21_FREE_MEM;
  107.         sr.es    = _psp;
  108.         int86x( INT21, &inr, &outr, &sr );
  109.     }
  110.  
  111.     /* shuffle stuff between the available buffers (do the real work!) */
  112.     /* transfer any characters from the incoming serial buffer
  113.        to tfpcx unless -R receive-only */
  114.     if ( ! rflag )
  115.         while ( ! com_rx_empty() )
  116.             tfpcx_writech( (u_char)com_rx() );
  117.  
  118.     /* transfer what we can from tfpcx to the serial buffer */
  119.     while ( com_tx_ready() && tfpcx_request() )
  120.         com_tx( (int)tfpcx_readch() );
  121. }
  122.  
  123.  
  124. /*-----------------------------------------------------------------------*/
  125. /*
  126.  * see if COM interrupts already in use - probably indicates either
  127.  * this TSR already loaded, or something else is using the port.  Note
  128.  * that this duplicates some definitions from ibmcom.c
  129.  */
  130. bool portbusy( int portnum )
  131. {
  132.     const char    i8259levels[] =    { 4,     3,     4,     3 };
  133.  
  134.     /* see if the 8259 bit for this port is clear (enabled) */
  135.     i8259bit  = 1 << i8259levels[portnum-1];
  136.     if ( ! (inportb( PIC_INTERRUPT_MASK_PORT ) & i8259bit))
  137.         return( TRUE );
  138.     else
  139.         return( FALSE );
  140. }
  141.  
  142.  
  143. /*-----------------------------------------------------------------------*/
  144. /*
  145.  * main program
  146.  */
  147. void main( int argc, char** argv )
  148. {
  149.     union    REGS inr,outr;        /* registers */
  150.     struct    SREGS sr;        /* registers */
  151.     int    com_retcode;        /* retcode from com_ routine */
  152.  
  153.     /* resolve the command line arguments */
  154.     if (! getopts( argc, argv )) {
  155.         printf( "\nTFLINK not installed\n" );
  156.         exit( 1 );
  157.     }
  158.  
  159.     /* handle unloading of already running TSR */
  160.     if ( uflag ) {
  161.         /* see if PIC IRQ set (bit clear) for the port */
  162.         if ( ! portbusy( sio_port )) {
  163.             printf( "\nCOM%d is not busy - TFLINK not running\n",
  164.                     sio_port );
  165.             exit( 1 );
  166.         }
  167.         /* set the bit - disable PIC UART interrupts - the
  168.            running TSR should spot this and drop out */
  169.         outportb( PIC_INTERRUPT_MASK_PORT,
  170.                 inportb( PIC_INTERRUPT_MASK_PORT) | i8259bit );
  171.  
  172.         /* job done */
  173.         if (! nflag)
  174.             printf( "\nTFLINK unloaded\n" );
  175.         exit( 0 );
  176.     }
  177.  
  178.     /* not unload - confirm options to user unless -N used */
  179.     if (! nflag)
  180.         printopts();
  181.  
  182.     /* check that the port is not already in use (by us?) */
  183.     if ( portbusy( sio_port )) {
  184.         printf( "\nCOM%d is busy - TFLINK may already be running\n",
  185.                 sio_port );
  186.         printf( "TFLINK not installed\n" );
  187.         exit( 1 );
  188.     }
  189.  
  190.     /* check for the presence of TFPCX at the expected interrupt */
  191.     if (! tfpcx_check() ) {
  192.         printf( "\nTFPCX not found at interrupt 0x%02X, exiting\n",
  193.                 tfpcx_interrupt );
  194.         printf( "TFLINK not installed\n" );
  195.         exit( 1 );
  196.     }
  197.  
  198.     /* print TFPCX version installed */
  199.     if (! nflag) {
  200.         printf( "\nTFPCX version %d.%d found at 0x%02X\n", 
  201.                 (u_int)(tfpcx_version() >> 8),
  202.                 (u_int)(tfpcx_version() & 0xFF),
  203.                 tfpcx_interrupt );
  204.     }
  205.  
  206.     /* set up UART to requested data rate */
  207.     if ( (com_retcode=com_install( sio_port )) != 0 ) {
  208.         printf( "\ncom_install() error %d\n", com_retcode );
  209.         printf( "TFLINK not installed\n" );
  210.         exit( 1 );
  211.     }
  212.     com_raise_dtr();
  213.     com_set_speed( sio_baud );
  214.     com_set_parity( COM_NONE, 1 );
  215.  
  216.     /* hook int 1C timer clock interrupt */
  217.     disable();
  218.     old_int_1c = getvect( INT1C );
  219.     setvect( INT1C, int_1c );
  220.     enable();
  221.  
  222.     /* free environment space memory - not required */
  223.     inr.h.ah = INT21_FREE_MEM;
  224.     sr.es    = (u_int)peek( _psp, 0x2C );
  225.     int86x( INT21, &inr, &outr, &sr );
  226.  
  227.     /* install this program as a TSR */
  228.     inr.h.ah = INT21_TSR;
  229.     inr.h.al = 0x00;
  230.     inr.x.dx = TSR_MEMORY;
  231.     int86( INT21, &inr, &outr );
  232. }
  233.